﻿using System.Diagnostics;

using Game.Actions;
using Game.Common;
using Game.Level;
using Game.Map;
using Game.Map.Extensions;
using Game.PathFinder;
using Game.StateMachine;

namespace Game.Ai.Internal.States.Patrol
{
    class StateIdPersue : StateId
    {
        public StateIdPersue() : base("PersueState") {}
    }
    
    class PersueState : State
    {
        readonly ActionExecutor _actionExecutor;
        
        public PersueState(ActionExecutor actionExecutor)
            : base(new StateIdPersue())
        {
            _actionExecutor = actionExecutor;
        }
        
        public override StateId CheckTransitions(object contoller)
        {
            var ai = contoller as AiController;
            
            var field = AiUtil.FindOther(ai);
            if (field != null)
            {
                Debug.Assert(ai != null, "ai != null");
                var vehicleField = ai.GameMapView.FindItem(ai.Vehicle);
                
                bool adjacent = StateUtil.InAdjacentField(ai, field, vehicleField);
                if (adjacent)
                {
                    return new StateIdAttack();
                }
            }
            
            return new StateIdPersue();
        }

        public override void DoTurn(
            IGameMapView view, 
            GameLevels levels,
            object contoller, 
            GameTurn turn)
        {
            for(;;)
            {
                var ai = contoller as AiController;
                Debug.Assert(ai != null, "ai != null");

                if (ai.Vehicle.Movement.Value <= 0)
                {
                    break;
                }
                
                var otherField = AiUtil.FindOther(ai);
                if (otherField == null)
                {
                    break;
                }

                var field = ai.GameMapView.FindItem(ai.Vehicle);
                if (field == null || field.VehicleX().Vehicle == null)
                {
                    break;
                }
                
                var finder = FinderFactory.Create(ai.GameMapView, field, otherField);
                var path = finder.Find();
                if (path == null)
                {
                    break;
                }

                var next = path.Points[1];
                var shortPath = GamePath.CreateDirectPath(path.FirstPoint, next);
                if (shortPath.CalcTerrainCost(ai.GameMap) > ai.Vehicle.Movement.Value)
                {
                    break;
                }
                
                if (!ai.GameMapView.Fields.Contains(next))
                {
                    break;
                }
                
                var end = ai.GameMapView.Fields[next];
                var pair = new GamePath(field.Point, end.Point);
                
                bool same = (field.Point.X == end.Point.X &&
                             field.Point.Y == end.Point.Y);
                GameDebug.Assert(!same);
                
                var move = new MoveUnit(ai.GameMapView, ai.Vehicle, pair);
                if (move.CanExecute())
                {
                    _actionExecutor.ExecuteLater(ai.GameMapView, levels, turn, move);
                }
                else
                {
                    move.CanExecute();
                    GameDebug.Assert(false);
                }
                
                break;
            }
        }

    }
}
